1 using ExitGames.Client.Photon;
2 using
UnityEngine;
3
4
5 ///
<summary>
6 ///
Simple script that uses a property to sync a start time for a multiplayer game.
7 ///
</summary>
8 ///
<remarks>
9 ///
When entering a room, the first player will store the synchronized timestamp.
10 ///
You can't set the room's synchronized time in CreateRoom, because the clock on the Master Server
11 ///
and those on the Game Servers are not in sync. We use many servers and each has it's own timer.
12 ///

13 ///
Everyone else will join the room and check the property to calculate how much time passed since start.
14 ///
You can start a new round whenever you like.
15 ///

16 ///
Based on this, you should be able to implement a synchronized timer for turns between players.
17 ///
</remarks>
18 public
class InRoomRoundTimer : MonoBehaviour
19 {
20     
public int SecondsPerTurn = 5; // time per round/turn
21     
public double StartTime; // this should could also be a private. i just like to see this in inspector
22     
public Rect TextPos = new Rect(0,80,150,300); // default gui position. inspector overrides this!
23
24     
private bool startRoundWhenTimeIsSynced; // used in an edge-case when we wanted to set a start time but don't know it yet.
25     
private const string StartTimeKey = "st"; // the name of our "start time" custom property.
26
27
28     
private void StartRoundNow()
29     {
30         
// in some cases, when you enter a room, the server time is not available immediately.
31         
// time should be 0.0f but to make sure we detect it correctly, check for a very low value.
32         
if (PhotonNetwork.time < 0.0001f)
33         {
34             
// we can only start the round when the time is available. let's check that in Update()
35             startRoundWhenTimeIsSynced =
true;
36             
return;
37         }
38         startRoundWhenTimeIsSynced =
false;
39
40         
41
42         ExitGames.Client.Photon.Hashtable startTimeProp =
new Hashtable(); // only use ExitGames.Client.Photon.Hashtable for Photon
43         startTimeProp[StartTimeKey] = PhotonNetwork.time;
44         PhotonNetwork.room.SetCustomProperties(startTimeProp);
// implement OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged) to get this change everywhere
45     }

46
47     
48     ///
<summary>Called by PUN when this client entered a room (no matter if joined or created).</summary>
49     
public void OnJoinedRoom()
50     {
51         
if (PhotonNetwork.isMasterClient)
52         {
53             
this.StartRoundNow();
54         }
55         
else
56         {
57             
// as the creator of the room sets the start time after entering the room, we may enter a room that has no timer started yet
58             Debug.Log(
"StartTime already set: " + PhotonNetwork.room.customProperties.ContainsKey(StartTimeKey));
59         }
60     }

61
62     ///
<summary>Called by PUN when new properties for the room were set (by any client in the room).</summary>
63     
public void OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged)
64     {
65         
if (propertiesThatChanged.ContainsKey(StartTimeKey))
66         {
67             StartTime = (
double)propertiesThatChanged[StartTimeKey];
68         }
69     }

70
71     ///
<remarks>
72     ///
In theory, the client which created the room might crash/close before it sets the start time.
73     ///
Just to make extremely sure this never happens, a new masterClient will check if it has to
74     ///
start a new round.
75     ///
</remarks>
76     
public void OnMasterClientSwitched(PhotonPlayer newMasterClient)
77     {
78         
if (!PhotonNetwork.room.customProperties.ContainsKey(StartTimeKey))
79         {
80             Debug.Log(
"The new master starts a new round, cause we didn't start yet.");
81             
this.StartRoundNow();
82         }
83     }
84
85
86     
void Update()
87     {
88         
if (startRoundWhenTimeIsSynced)
89         {
90             
this.StartRoundNow(); // the "time is known" check is done inside the method.
91         }
92     }
93
94     
public void OnGUI()
95     {
96         
// alternatively to doing this calculation here:
97         
// calculate these values in Update() and make them publicly available to all other scripts
98         
double elapsedTime = (PhotonNetwork.time - StartTime);
99         
double remainingTime = SecondsPerTurn - (elapsedTime % SecondsPerTurn);
100         
int turn = (int)(elapsedTime / SecondsPerTurn);
101
102
103         
// simple gui for output
104         GUILayout.BeginArea(TextPos);
105         GUILayout.Label(
string.Format("elapsed: {0:0.000}", elapsedTime));
106         GUILayout.Label(
string.Format("remaining: {0:0.000}", remainingTime));
107         GUILayout.Label(
string.Format("turn: {0:0}", turn));
108         
if (GUILayout.Button("new round"))
109         {
110             
this.StartRoundNow();
111         }
112         GUILayout.EndArea();
113     }
114 }


Simple script that uses a property to sync a start time for a multiplayer game.

When entering a room, the first player will store the synchronized timestamp.

You can't set the room's synchronized time in CreateRoom, because the clock on the Master Server

and those on the Game Servers are not in sync. We use many servers and each has it's own timer.

Everyone else will join the room and check the property to calculate how much time passed since start.

You can start a new round whenever you like.

Based on this, you should be able to implement a synchronized timer for turns between players.

public int SecondsPerTurn = 5; time per roundturn

public double StartTime; this should could also be a private. i just like to see this in inspector

public Rect TextPos = new Rect(0,80,150,300); default gui position. inspector overrides this!

private bool startRoundWhenTimeIsSynced; used in an edge-case when we wanted to set a start time but don't know it yet.

private const string StartTimeKey = "st"; the name of our "start time" custom property.

in some cases, when you enter a room, the server time is not available immediately.

time should be 0.0f but to make sure we detect it correctly, check for a very low value.

we can only start the round when the time is available. let's check that in Update()

ExitGames.Client.Photon.Hashtable startTimeProp = new Hashtable(); only use ExitGames.Client.Photon.Hashtable for Photon

PhotonNetwork.room.SetCustomProperties(startTimeProp); implement OnPhotonCustomRoomPropertiesChanged(Hashtable propertiesThatChanged) to get this change everywhere

Called by PUN when this client entered a room (no matter if joined or created).

as the creator of the room sets the start time after entering the room, we may enter a room that has no timer started yet

Called by PUN when new properties for the room were set (by any client in the room).

In theory, the client which created the room might crashclose before it sets the start time.

Just to make extremely sure this never happens, a new masterClient will check if it has to

start a new round.

this.StartRoundNow(); the "time is known" check is done inside the method.

alternatively to doing this calculation here:

calculate these values in Update() and make them publicly available to all other scripts

simple gui for output




Trò chơi Tic-Tac-Toe, game đánh caro full source code 53.586 lượt xem

Gõ tìm kiếm nhanh...